<template>
  <div class="app-container">
    <!-- 页面头部 -->
    <PageHeader back-text="返回项目列表" back-type="back" :title="projectInfo.proName || '加载中...'" />

    <!-- 项目详情卡片 -->
    <ProjectDetail :project-info="projectInfo" :loading="projectLoading" />

    <!-- 回款统计卡片 -->
    <el-card class="mb-6 statistics-card">
      <template #header>
        <div class="statistics-header">
          <el-icon class="statistics-icon">
            <Money />
          </el-icon>
          <span class="statistics-title">子项目回款统计汇总</span>
        </div>
      </template>
      <div class="statistics-grid">
        <div class="stat-item">
          <div class="stat-label">应收金额总计</div>
          <div class="stat-value total-amount">{{ formatAmount(totalStatistics.totalAmount) }}元</div>
          <div class="stat-desc">所有回款节点应收金额</div>
        </div>
        <div class="stat-item">
          <div class="stat-label">已收金额总计</div>
          <div class="stat-value received-amount">{{ formatAmount(totalStatistics.receivedAmount) }}元</div>
          <div class="stat-desc">已实际收到的金额</div>
        </div>
        <div class="stat-item">
          <div class="stat-label">剩余金额总计</div>
          <div class="stat-value surplus-amount">{{ formatAmount(totalStatistics.surplusAmount) }}元</div>
          <div class="stat-desc">尚未收回的金额</div>
        </div>
        <div class="stat-item">
          <div class="stat-label">回款完成率</div>
          <div class="stat-value completion-rate">{{ calculateCompletionRate() }}%</div>
          <div class="stat-desc">已收金额占应收金额比例</div>
        </div>
      </div>
    </el-card>

    <!-- 回款信息卡片 -->
    <el-card class="mb-6 box-card receive-card" v-loading="loading">
      <!-- 回款信息操作按钮 -->
      <div class="card-header mb-4">
        <div class="card-header-left">
          <span class="title">回款信息</span>
          <el-dropdown @command="handleMoreCommand" v-hasPermi="['project:receive:import', 'project:receive:export']">
            <el-button type="warning" plain size="default">
              导入导出
              <el-icon class="el-icon--right">
                <ArrowDown />
              </el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="download-template">
                  <el-icon style="vertical-align: middle">
                    <Download />
                  </el-icon>
                  <span style="margin-left: 4px">下载模板</span>
                </el-dropdown-item>
                <el-dropdown-item command="import-data">
                  <el-icon style="vertical-align: middle">
                    <Upload />
                  </el-icon>
                  <span style="margin-left: 4px">导入数据</span>
                </el-dropdown-item>
                <el-dropdown-item command="export-data">
                  <el-icon style="vertical-align: middle">
                    <Download />
                  </el-icon>
                  <span style="margin-left: 4px">导出数据</span>
                </el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
          <div style="display: flex; align-items: center; gap: 8px">
            <el-select v-model="sortField" placeholder="请选择排序字段" style="width: 170px" clearable
              @change="handleSortChange">
              <el-option label="付款节点" value="nodeTitle" />
              <el-option label="收款负责人" value="nodeLeadersId" />
              <el-option label="到账金额" value="receivedAmount" />
            </el-select>
            <el-button v-if="sortField" :icon="sortOrder === 'asc' ? ArrowUp : ArrowDown" @click="toggleSortOrder"
              type="info" plain size="small" :title="sortOrder === 'asc' ? '当前为正序，点击切换为逆序' : '当前为逆序，点击切换为正序'">
              {{ sortOrder === 'asc' ? '正序' : '逆序' }}
            </el-button>
          </div>
        </div>
        <div class="right">
          <div class="flex items-center" style="gap: 12px">
            <RefreshButton @refresh="handleQuery" />
          </div>
        </div>
      </div>

      <!-- 回款信息表格 -->
      <div class="receive-container">
        <el-table :data="receiveList" border style="width: 100%" row-key="id" :row-class-name="tableRowClassName">
          <!-- 付款节点 -->
          <el-table-column label="付款节点" align="center" width="200" fixed="left" :show-overflow-tooltip="true">
            <template #default="scope">
              <span>{{ scope.row.nodeTitle || '-' }}</span>
            </template>
          </el-table-column>

          <!-- 收款负责人 -->
          <el-table-column label="收款负责人" align="center" width="200">
            <template #default="scope">
              <div v-if="scope.row.isEditing" class="inline-user-selector">
                <div class="selected-users-inline">
                  <el-tag v-for="leader in getSelectedLeaders(scope.row)" :key="leader.userId" closable
                    @close="removeInlineLeader(scope.row, leader)" size="small" type="success">
                    {{ leader.userName || leader.nickName }}
                  </el-tag>
                </div>
                <el-button size="small" type="success" plain @click="openLeaderSelector(scope.row)"
                  class="inline-select-btn"> 选择 </el-button>
              </div>
              <span v-else>{{ scope.row.nodeLeadersName || '-' }}</span>
            </template>
          </el-table-column>

          <!-- 节点金额 -->
          <el-table-column label="该节点应收款金额" align="center" width="200">
            <template #default="scope">
              <MoneyInput v-if="scope.row.isEditing" v-model="scope.row.totalAmount" :min="0" placeholder="请输入应收金额（必填）"
                size="small" style="width: 100%"
                :class="{ 'is-error': !scope.row.totalAmount || scope.row.totalAmount <= 0 }"
                @change="calculateSurplusAmount(scope.row)" />
              <span v-else-if="scope.row.totalAmount">{{ formatAmount(scope.row.totalAmount) }}元</span>
              <span v-else>-</span>
            </template>
          </el-table-column>

          <!-- 已收金额 -->
          <el-table-column label="该节点已回款金额" align="center" width="200">
            <template #default="scope">
              <MoneyInput v-if="scope.row.isEditing" v-model="scope.row.receivedAmount" :min="0" placeholder="请输入已收金额"
                size="small" style="width: 100%" @change="calculateSurplusAmount(scope.row)" />
              <span v-else-if="scope.row.receivedAmount">{{ formatAmount(scope.row.receivedAmount) }}元</span>
              <span v-else class="text-gray-400">0.00元</span>
            </template>
          </el-table-column>

          <!-- 剩余金额 -->
          <el-table-column label="该节点剩余应收款金额" align="center" width="200">
            <template #default="scope">
              <span style="color: #f56c6c; font-weight: bold">{{ formatAmount(scope.row.surplusAmount) }}元</span>
            </template>
          </el-table-column>

          <!-- 收款状态 -->
          <el-table-column label="收款状态" align="center" width="200">
            <template #default="scope">
              <el-select v-if="scope.row.isEditing" v-model="scope.row.receiveStatus" placeholder="请选择收款状态" size="small"
                style="width: 100%">
                <el-option v-for="dict in pro_receive_node_status" :key="dict.value" :label="dict.label"
                  :value="dict.value" />
              </el-select>
              <dict-tag v-else :options="pro_receive_node_status" :value="scope.row.receiveStatus || ''" />
            </template>
          </el-table-column>

          <!-- 是否到达回款节点 -->
          <el-table-column label="是否达到回款节点" align="center" width="200">
            <template #default="scope">
              <dict-tag :options="pro_receive_is_arrive" :value="scope.row.isArrive || ''" />
            </template>
          </el-table-column>

          <!-- 下一步计划 -->
          <el-table-column label="最新收款情况及下一步计划" align="center" width="400">
            <template #default="scope">
              <el-input v-if="scope.row.isEditing" v-model="scope.row.nextPlan" :rows="4" type="textarea"
                placeholder="请输入下一步计划" size="small" />
              <el-tooltip v-else :content="scope.row.nextPlan" placement="top" :disabled="!scope.row.nextPlan">
                <span class="text-overflow">{{ scope.row.nextPlan || '-' }}</span>
              </el-tooltip>
            </template>
          </el-table-column>

          <!-- 备注 -->
          <el-table-column label="备注" align="center" width="400">
            <template #default="scope">
              <el-input v-if="scope.row.isEditing" v-model="scope.row.remark" :rows="4" type="textarea"
                placeholder="请输入备注" size="small" />
              <el-tooltip v-else :content="scope.row.remark" placement="top" :disabled="!scope.row.remark">
                <span class="text-overflow">{{ scope.row.remark || '-' }}</span>
              </el-tooltip>
            </template>
          </el-table-column>

          <!-- 创建时间 -->
          <el-table-column label="更新时间" align="center" fixed="right" prop="updateTime" width="150">
            <template #default="scope">
              {{ scope.row.updateTime ? scope.row.updateTime : '-' }}
            </template>
          </el-table-column>

          <!-- 状态 -->
          <el-table-column label="保存状态" width="150" fixed="right" align="center">
            <template #default="scope">
              <el-tag :type="scope.row.id ? 'success' : 'warning'">
                {{ scope.row.id ? '已保存' : '未保存' }}
              </el-tag>
            </template>
          </el-table-column>

          <!-- 操作 -->
          <el-table-column label="操作" width="150" fixed="right" align="center">
            <template #default="scope">
              <!-- 编辑模式下的操作按钮 -->
              <template v-if="scope.row.isEditing">
                <el-button size="small" type="primary" @click="saveReceive(scope.row)" :loading="scope.row.saving"> 保存
                </el-button>
                <el-button size="small" type="danger" @click="cancelEdit(scope.row)" :disabled="scope.row.saving"> 取消
                </el-button>
              </template>
              <!-- 查看模式下的操作按钮 -->
              <template v-else>
                <el-tooltip content="修改" placement="top">
                  <el-button link type="primary" icon="Edit" @click="editReceive(scope.row)"
                    v-hasPermi="['project:receive:edit']"></el-button>
                </el-tooltip>
                <el-tooltip content="查看日志" placement="top">
                  <el-button link type="info" icon="List" @click="viewReceiveLog(scope.row)"
                    v-hasPermi="['project:receive:log']"></el-button>
                </el-tooltip>
              </template>
            </template>
          </el-table-column>

          <template #empty>
            <el-empty description="暂无回款数据" />
          </template>
        </el-table>
      </div>

      <!-- 底部信息容器 - 使用组件 -->
      <ProjectBottomInfo :project-list="receiveList" />
    </el-card>
    <!-- UserSelector组件 -->
    <UserSelector v-model:visible="leaderSelectorVisible" :title="'选择收款负责人'" :multiple="true"
      :selected-user-ids="currentLeaderRow?.nodeLeadersId || ''"
      :selected-user-names="currentLeaderRow?.nodeLeadersName || ''" @confirmWithIds="handleLeaderSelectorConfirm"
      @cancel="handleLeaderSelectorCancel" />

    <!-- 日志查看弹窗 -->
    <el-dialog v-model="logDialogVisible" :title="`${currentLogNode?.nodeTitle || '回款节点'} - 修改记录`" width="900px"
      destroy-on-close class="log-dialog" @close="handleLogDialogClose">
      <div v-loading="logLoading" class="log-container">
        <!-- 统计图表区域 -->
        <el-card class="chart-card mb-4" v-if="logList.length > 0">
          <template #header>
            <div class="chart-header">
              <el-icon class="chart-icon">
                <TrendCharts />
              </el-icon>
              <span>回款完成率变化趋势</span>
            </div>
          </template>
          <div id="completionRateChart" style="width: 100%; height: 300px; min-height: 300px"></div>
        </el-card>

        <!-- 日志记录表格 -->
        <el-card>
          <template #header>
            <div class="log-header">
              <el-icon class="log-icon">
                <List />
              </el-icon>
              <span>修改记录详情</span>
            </div>
          </template>

          <el-table :data="logList" border style="width: 100%" v-if="logList.length > 0">
            <el-table-column label="修改时间" prop="logTime" width="150" align="center">
              <template #default="scope">
                {{ scope.row.logTime ? parseTime(scope.row.logTime, '{y}-{m}-{d} {h}:{i}:{s}') : '-' }}
              </template>
            </el-table-column>

            <el-table-column label="应收金额" prop="totalAmount" width="120" align="center">
              <template #default="scope">
                <span>{{ scope.row.totalAmount ? formatAmount(scope.row.totalAmount) + '元' : '-' }}</span>
              </template>
            </el-table-column>

            <el-table-column label="已收金额" prop="receivedAmount" width="120" align="center">
              <template #default="scope">
                <span>{{ scope.row.receivedAmount ? formatAmount(scope.row.receivedAmount) + '元' : '0.00元' }}</span>
              </template>
            </el-table-column>

            <el-table-column label="剩余金额" prop="surplusAmount" width="120" align="center">
              <template #default="scope">
                <span style="color: #f56c6c">{{ scope.row.surplusAmount ? formatAmount(scope.row.surplusAmount) + '元' :
                  '0.00元' }}</span>
              </template>
            </el-table-column>

            <el-table-column label="完成率" prop="receiveCompleteRate" width="100" align="center">
              <template #default="scope">
                <el-tag :type="getCompleteRateType(scope.row.receiveCompleteRate)">
                  {{ scope.row.receiveCompleteRate ? (Number(scope.row.receiveCompleteRate) * 100).toFixed(2) + '%' :
                  '0.00%' }}
                </el-tag>
              </template>
            </el-table-column>

            <el-table-column label="收款状态" prop="receiveStatus" width="120" align="center">
              <template #default="scope">
                <dict-tag :options="pro_receive_node_status" :value="scope.row.receiveStatus || ''" />
              </template>
            </el-table-column>

            <el-table-column label="下一步计划" prop="nextPlan" width="200" align="left">
              <template #default="scope">
                <el-tooltip :content="scope.row.nextPlan" placement="top" :disabled="!scope.row.nextPlan">
                  <span class="text-overflow">{{ scope.row.nextPlan || '-' }}</span>
                </el-tooltip>
              </template>
            </el-table-column>

            <el-table-column label="备注" prop="remark" width="200" align="left">
              <template #default="scope">
                <el-tooltip :content="scope.row.remark" placement="top" :disabled="!scope.row.remark">
                  <span class="text-overflow">{{ scope.row.remark || '-' }}</span>
                </el-tooltip>
              </template>
            </el-table-column>
          </el-table>

          <el-empty v-else description="暂无修改记录" />
        </el-card>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="logDialogVisible = false">关闭</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 导入对话框 -->
    <el-dialog v-model="upload.open" :title="upload.title" width="400px" append-to-body>
      <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
        :action="upload.url + '?proId=' + (queryParams as any).proId + '&updateSupport=' + upload.updateSupport"
        :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess"
        :auto-upload="false" drag>
        <el-icon class="el-icon--upload">
          <i-ep-upload-filled />
        </el-icon>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <template #tip>
          <div class="text-center el-upload__tip">
            <div class="el-upload__tip"><el-checkbox v-model="upload.updateSupport" />是否更新已经存在的回款数据</div>
            <span>仅允许导入xls、xlsx格式文件。</span>
            <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline"
              @click="handleImportTemplate">
              下载模板
            </el-link>
          </div>
        </template>
      </el-upload>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitFileForm">确 定</el-button>
          <el-button @click="upload.open = false">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { useRoute, useRouter } from 'vue-router';
import { getProDetail } from '@/api/project/init/proInfo';
import { parseTime } from '@/utils/ruoyi';
import type { ProInfoVO } from '@/api/project/init/proInfo/types';
import { listProReceiveMoney, updateProReceiveMoney, getReceiveMoneyLog } from '@/api/project/receive';
import type { ProReceiveMoneyQuery, ProReceiveMoneyVO, ProReceiveMoneyForm, ProReceiveLogVO } from '@/api/project/receive/types';
import ProjectDetail from '@/views/project/components/ProjectDetail.vue';
import PageHeader from '@/views/project/components/PageHeader/index.vue';
import ProjectBottomInfo from '@/views/project/components/ProjectBottomInfo.vue';
import RefreshButton from '@/views/project/components/RefreshButton.vue';
import UserSelector from '@/components/UserSelector/index.vue';
import DictTag from '@/components/DictTag/index.vue';
import { MoneyInput, formatAmount } from '@/components/NumberInput';
import { useDict } from '@/utils/dict';
import * as echarts from 'echarts';
import { ArrowUp, ArrowDown, Download, Upload } from '@element-plus/icons-vue';
import { globalHeaders } from '@/utils/request';

const route = useRoute();
const router = useRouter();

// 项目信息
const projectInfo = ref<Partial<ProInfoVO>>({});
const projectLoading = ref(false);

const { proxy } = getCurrentInstance() as any;
const { pro_receive_node_status, pro_receive_is_arrive, approval_commit_status } = useDict(
  'pro_receive_node_status',
  'pro_receive_is_arrive',
  'approval_commit_status'
);

// 回款列表
const receiveList = ref<ProReceiveMoneyVO[]>([]);

// 查询参数
const queryParams = ref<ProReceiveMoneyQuery>({
  proId: Number(route.params.proId)
});

// 加载状态
const loading = ref(false);

// 统计数据
const totalStatistics = ref({
  totalAmount: 0,
  receivedAmount: 0,
  surplusAmount: 0
});

// UserSelector相关状态
const userSelectorVisible = ref(false);
const currentEditingRow = ref<any>(null);
const userSelectorTitle = ref('选择收款负责人');

// 日志弹窗相关状态
const logDialogVisible = ref(false);
const logList = ref<any[]>([]);
const logLoading = ref(false);
const currentLogNode = ref<any>(null);
const chartInstance = ref<any>(null);
const chartResizeHandler = ref<any>(null);

// 收款负责人选择器相关状态
const leaderSelectorVisible = ref(false);
const currentLeaderRow = ref<any>(null);

// 排序相关状态
const sortField = ref<string | undefined>(undefined);
const sortOrder = ref<'asc' | 'desc'>('asc');

// 导入相关
const uploadRef = ref();
const upload = reactive({
  // 是否显示弹出层
  open: false,
  // 弹出层标题
  title: '',
  // 是否禁用上传
  isUploading: false,
  // 是否更新已经存在的回款数据
  updateSupport: 0,
  // 设置上传的请求头部
  headers: globalHeaders(),
  // 上传的地址
  url: import.meta.env.VITE_APP_BASE_API + '/pro/receive/importData'
});

const handleSortChange = () => {
  getReceiveList();
};
const toggleSortOrder = () => {
  sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc';
  getReceiveList();
};

/**
 * 打开用户选择器
 */
const openUserSelector = (row: any) => {
  currentEditingRow.value = row;
  userSelectorVisible.value = true;
};

/**
 * 用户选择确认回调
 */
const handleUserSelectorConfirm = (data: { users: any[]; userIds: string; userNames: string }) => {
  if (currentEditingRow.value) {
    // 验证数据
    if (!data.userIds || !data.userNames) {
      ElMessage.warning('请至少选择一个收款负责人');
      return;
    }

    currentEditingRow.value.nodeLeadersId = data.userIds;
    currentEditingRow.value.nodeLeadersName = data.userNames;
  }
  userSelectorVisible.value = false;
  currentEditingRow.value = null;
};

/**
 * 用户选择取消回调
 */
const handleUserSelectorCancel = () => {
  userSelectorVisible.value = false;
  currentEditingRow.value = null;
};

/**
 * 打开收款负责人选择器
 */
const openLeaderSelector = (row: any) => {
  currentLeaderRow.value = row;
  leaderSelectorVisible.value = true;
};

/**
 * 收款负责人选择确认回调
 */
const handleLeaderSelectorConfirm = (data: { users: any[]; userIds: string; userNames: string }) => {
  if (currentLeaderRow.value) {
    currentLeaderRow.value.nodeLeadersId = data.userIds;
    currentLeaderRow.value.nodeLeadersName = data.userNames;
    currentLeaderRow.value.nodeLeadersArr = data.users;
  }
  leaderSelectorVisible.value = false;
  currentLeaderRow.value = null;
};

/**
 * 收款负责人选择取消回调
 */
const handleLeaderSelectorCancel = () => {
  leaderSelectorVisible.value = false;
  currentLeaderRow.value = null;
};

/**
 * 获取已选择的收款负责人
 */
const getSelectedLeaders = (row: any) => {
  if (row.nodeLeadersArr) return row.nodeLeadersArr;
  if (row.nodeLeadersId && row.nodeLeadersName) {
    const ids = row.nodeLeadersId.split(',');
    const names = row.nodeLeadersName.split(',');
    return ids.map((id: string, idx: number) => ({
      userId: id,
      userName: names[idx] || ''
    }));
  }
  return [];
};

/**
 * 移除已选择的收款负责人
 */
const removeInlineLeader = (row: any, leader: any) => {
  const arr = getSelectedLeaders(row).filter((u: any) => u.userId !== leader.userId);
  row.nodeLeadersArr = arr;
  row.nodeLeadersId = arr.map((u: any) => u.userId).join(',');
  row.nodeLeadersName = arr.map((u: any) => u.userName || u.nickName).join(',');
};

/**
 * 刷新数据
 */
const handleQuery = () => {
  getReceiveList();
};

/**
 * 获取回款列表数据
 */
const getReceiveList = async () => {
  try {
    loading.value = true;
    const params: any = { proId: queryParams.value.proId };
    if (sortField.value) {
      params.orderByColumn = sortField.value;
      params.isAsc = sortOrder.value;
    }
    const res = await listProReceiveMoney(params);
    receiveList.value = (res.data || []).map((item) => ({
      ...item,
      isEditing: false,
      saving: false,
      originalData: null
    }));
    // 计算统计数据
    calculateTotalStatistics();
  } catch (error) {
    console.error('获取回款节点列表失败:', error);
  } finally {
    loading.value = false;
  }
};

/**
 * 获取项目信息
 */
const getProjectDetail = async () => {
  const proId = route.params.proId as string;
  if (!proId) {
    ElMessage.error('项目ID不能为空');
    return;
  }

  try {
    projectLoading.value = true;
    const res = await getProDetail(proId);
    projectInfo.value = res.data || {};
  } catch (error) {
    console.error('获取项目信息失败:', error);
  } finally {
    projectLoading.value = false;
  }
};

/**
 * 安全转换金额数值
 */
const safeNumber = (value: any): number => Number(value) || 0;

/**
 * 计算剩余金额
 */
const calculateSurplusAmount = (row: any) => {
  const totalAmount = safeNumber(row.totalAmount);
  const receivedAmount = safeNumber(row.receivedAmount);
  row.surplusAmount = Number((totalAmount - receivedAmount).toFixed(2));
  // 重新计算统计数据
  calculateTotalStatistics();
};

/**
 * 计算总统计数据
 */
const calculateTotalStatistics = () => {
  const totals = receiveList.value.reduce(
    (acc, item) => ({
      totalAmount: acc.totalAmount + safeNumber(item.totalAmount),
      receivedAmount: acc.receivedAmount + safeNumber(item.receivedAmount),
      surplusAmount: acc.surplusAmount + safeNumber(item.surplusAmount)
    }),
    { totalAmount: 0, receivedAmount: 0, surplusAmount: 0 }
  );

  totalStatistics.value = {
    totalAmount: Number(totals.totalAmount.toFixed(2)),
    receivedAmount: Number(totals.receivedAmount.toFixed(2)),
    surplusAmount: Number(totals.surplusAmount.toFixed(2))
  };
};

/**
 * 计算回款完成率
 */
const calculateCompletionRate = () => {
  if (totalStatistics.value.totalAmount === 0) return '0.00';
  const rate = (totalStatistics.value.receivedAmount / totalStatistics.value.totalAmount) * 100;
  return rate.toFixed(2);
};

/**
 * 编辑回款
 */
const editReceive = async (row: any) => {
  try {
    // 保存原始数据用于取消时恢复
    row.originalData = JSON.parse(JSON.stringify(row));
    row.isEditing = true;
    row.saving = false;
  } catch (error) {
    console.error('编辑回款失败:', error);
    ElMessage.error('编辑回款失败');
  }
};

/**
 * 校验单行数据
 */
const validateReceiveRow = (row: any): { valid: boolean; errors: string[] } => {
  const errors: string[] = [];

  // 必填字段校验（付款节点现在是只读的，不需要验证）
  if (row.totalAmount === undefined || row.totalAmount === null || row.totalAmount === '') {
    errors.push('应收金额不能为空');
  } else if (row.totalAmount <= 0) {
    errors.push('应收金额必须大于0');
  }

  // 收款负责人必填校验
  if (!row.nodeLeadersId || !row.nodeLeadersName) {
    errors.push('收款负责人不能为空');
  }

  // 非负数校验
  if (row.receivedAmount !== undefined && row.receivedAmount !== null && row.receivedAmount !== '' && row.receivedAmount < 0) {
    errors.push('已收金额不能为负');
  }

  return {
    valid: errors.length === 0,
    errors
  };
};

/**
 * 保存回款
 */
const saveReceive = async (row: any) => {
  // 先进行数据校验
  const validation = validateReceiveRow(row);
  if (!validation.valid) {
    ElMessage.error(`保存失败：${validation.errors.join('；')}`);
    return;
  }

  row.saving = true;
  try {
    // 封装回款节点数据
    const nodeData: ProReceiveMoneyForm = {
      id: row.id,
      proId: row.proId,
      totalAmount: row.totalAmount,
      receivedAmount: row.receivedAmount,
      surplusAmount: row.surplusAmount,
      nextPlan: row.nextPlan,
      nodeTitle: row.nodeTitle,
      nodeLeadersId: row.nodeLeadersId,
      receiveStatus: row.receiveStatus,
      remark: row.remark
    };

    // 调用后端接口保存
    await updateProReceiveMoney(nodeData);

    ElMessage.success('保存成功');
    row.isEditing = false;
    row.originalData = null;

    // 重新获取数据
    getReceiveList();
  } catch (error) {
    console.error('保存回款失败:', error);
    ElMessage.error('保存失败');
  } finally {
    row.saving = false;
  }
};

/**
 * 取消编辑
 */
const cancelEdit = (row: any) => {
  if (row.originalData) {
    // 恢复原始数据
    Object.assign(row, row.originalData);
    row.isEditing = false;
    row.originalData = null;
  } else {
    // 新增的行，直接从列表中移除
    const index = receiveList.value.findIndex((item) => item === row);
    if (index > -1) {
      receiveList.value.splice(index, 1);
    }
  }
};

/**
 * 处理更多操作命令
 */
const handleMoreCommand = (command: string) => {
  switch (command) {
    case 'download-template':
      handleImportTemplate();
      break;
    case 'import-data':
      handleImport();
      break;
    case 'export-data':
      handleExport();
      break;
    default:
      break;
  }
};

/**
 * 导出数据
 */
const handleExport = () => {
  const exportParams = { proId: (queryParams as any).proId };
  proxy?.download('pro/receive/export', exportParams, `project_receive_money_${new Date().getTime()}.xlsx`);
};

/**
 * 下载导入模板
 */
const handleImportTemplate = () => {
  proxy?.download('pro/receive/importTemplate', {}, `project_receive_money_template_${new Date().getTime()}.xlsx`);
};

/**
 * 导入按钮操作
 */
const handleImport = () => {
  if (!(queryParams as any).proId) {
    ElMessage.error('项目ID不能为空');
    return;
  }
  upload.title = '项目回款导入';
  upload.open = true;
  upload.isUploading = false;
  upload.updateSupport = 0;

  if (uploadRef.value) {
    uploadRef.value.clearFiles();
  }
};

/**
 * 文件上传中处理
 */
const handleFileUploadProgress = () => {
  upload.isUploading = true;
};

/**
 * 文件上传成功处理
 */
const handleFileSuccess = (response: any) => {
  upload.open = false;
  upload.isUploading = false;
  uploadRef.value?.clearFiles();

  // 导入结果弹出
  ElMessageBox.alert(response.msg, '导入结果', {
    dangerouslyUseHTMLString: true,
    confirmButtonText: '确定',
    type: 'success'
  });
  // 重新获取回款列表和项目详情
  getReceiveList();
  getProjectDetail();
};

/**
 * 提交上传文件
 */
const submitFileForm = () => {
  uploadRef.value?.submit();
};

/**
 * 查看回款节点日志
 */
const viewReceiveLog = async (row: any) => {
  if (!row.id) {
    ElMessage.warning('该节点尚未保存，无法查看日志');
    return;
  }

  currentLogNode.value = row;
  logDialogVisible.value = true;

  try {
    logLoading.value = true;
    const res = await getReceiveMoneyLog(row.id);
    logList.value = res.data || [];

    // 绘制图表
    if (logList.value.length > 0) {
      nextTick(() => {
        // 额外延时确保DOM完全渲染
        setTimeout(() => {
          renderCompletionRateChart();
        }, 100);
      });
    }
  } catch (error) {
    console.error('获取日志失败:', error);
    ElMessage.error('获取日志失败');
  } finally {
    logLoading.value = false;
  }
};

/**
 * 处理日志弹窗关闭
 */
const handleLogDialogClose = () => {
  // 清理resize事件监听器
  if (chartResizeHandler.value) {
    window.removeEventListener('resize', chartResizeHandler.value);
    chartResizeHandler.value = null;
  }

  // 清理图表实例
  if (chartInstance.value) {
    chartInstance.value.dispose();
    chartInstance.value = null;
  }

  // 清理数据
  logList.value = [];
  currentLogNode.value = null;
};

/**
 * 获取完成率标签类型
 */
const getCompleteRateType = (rate: number | null | undefined) => {
  if (!rate) return 'info';
  const rateNum = Number(rate) * 100;
  if (rateNum >= 100) return 'success';
  if (rateNum >= 80) return 'success';
  if (rateNum >= 50) return 'warning';
  return 'danger';
};

/**
 * 渲染完成率趋势图表
 */
const renderCompletionRateChart = () => {
  try {
    const chartDom = document.getElementById('completionRateChart');
    if (!chartDom) {
      console.warn('图表容器不存在');
      return;
    }

    // 处理数据
    if (!logList.value || logList.value.length === 0) {
      chartDom.innerHTML = '<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #909399;">暂无数据</div>';
      return;
    }

    // 清空容器内容，准备渲染图表
    chartDom.innerHTML = '';

    // 销毁之前的图表实例
    if (chartInstance.value) {
      chartInstance.value.dispose();
      chartInstance.value = null;
    }

    const myChart = echarts.init(chartDom);
    chartInstance.value = myChart;

    // 处理图表数据
    const chartData = logList.value.map((item) => ({
      time: item.logTime ? parseTime(item.logTime, '{m}-{d} {h}:{i}') : '',
      rate: Number((safeNumber(item.receiveCompleteRate) * 100).toFixed(2)),
      totalAmount: safeNumber(item.totalAmount),
      receivedAmount: safeNumber(item.receivedAmount)
    }));

    const timeData = chartData.map((item) => item.time);
    const rateData = chartData.map((item) => item.rate);
    const totalAmountData = chartData.map((item) => item.totalAmount);
    const receivedAmountData = chartData.map((item) => item.receivedAmount);

    const option = {
      title: {
        text: '回款完成率变化趋势',
        left: 'center',
        textStyle: {
          color: '#303133',
          fontSize: 16,
          fontWeight: 'bold'
        }
      },
      tooltip: {
        trigger: 'axis',
        backgroundColor: 'rgba(255, 255, 255, 0.95)',
        borderColor: '#e4e7ed',
        borderWidth: 1,
        textStyle: {
          color: '#606266'
        },
        formatter: function (params) {
          let html = `<div style="margin-bottom: 6px; font-weight: bold;">${params[0].axisValue}</div>`;
          params.forEach((param) => {
            const value = param.seriesName === '回款完成率' ? `${param.value}%` : `¥${Number(param.value).toLocaleString()}`;
            html += `<div style="margin: 2px 0;">
              <span style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background-color: ${param.color}; margin-right: 8px;"></span>
              ${param.seriesName}: <span style="font-weight: bold;">${value}</span>
            </div>`;
          });
          return html;
        }
      },
      legend: {
        data: ['回款完成率', '应收金额', '已收金额'],
        top: 30,
        textStyle: {
          color: '#606266'
        }
      },
      grid: {
        left: '3%',
        right: '8%',
        bottom: '3%',
        top: '15%',
        containLabel: true
      },
      xAxis: {
        type: 'category',
        data: timeData,
        boundaryGap: false,
        axisLabel: {
          color: '#909399',
          fontSize: 12,
          rotate: timeData.length > 6 ? 45 : 0
        },
        axisLine: {
          lineStyle: {
            color: '#e4e7ed'
          }
        }
      },
      yAxis: [
        {
          type: 'value',
          name: '完成率(%)',
          position: 'left',
          min: 0,
          max: 100,
          axisLabel: {
            formatter: '{value}%',
            color: '#909399'
          },
          axisLine: {
            lineStyle: {
              color: '#e4e7ed'
            }
          },
          splitLine: {
            lineStyle: {
              color: '#f5f7fa'
            }
          }
        },
        {
          type: 'value',
          name: '金额(元)',
          position: 'right',
          axisLabel: {
            formatter: function (value) {
              if (value >= 10000) {
                return (value / 10000).toFixed(1) + '万';
              }
              return value.toLocaleString();
            },
            color: '#909399'
          },
          axisLine: {
            lineStyle: {
              color: '#e4e7ed'
            }
          }
        }
      ],
      series: [
        {
          name: '回款完成率',
          type: 'line',
          yAxisIndex: 0,
          data: rateData,
          smooth: true,
          symbolSize: 8,
          lineStyle: {
            color: '#409EFF',
            width: 3
          },
          itemStyle: {
            color: '#409EFF',
            borderColor: '#fff',
            borderWidth: 2
          },
          areaStyle: {
            color: {
              type: 'linear',
              x: 0,
              y: 0,
              x2: 0,
              y2: 1,
              colorStops: [
                {
                  offset: 0,
                  color: 'rgba(64, 158, 255, 0.3)'
                },
                {
                  offset: 1,
                  color: 'rgba(64, 158, 255, 0.1)'
                }
              ]
            }
          }
        },
        {
          name: '应收金额',
          type: 'line',
          yAxisIndex: 1,
          data: totalAmountData,
          smooth: true,
          symbolSize: 6,
          lineStyle: {
            color: '#F56C6C',
            width: 2,
            type: 'dashed'
          },
          itemStyle: {
            color: '#F56C6C'
          }
        },
        {
          name: '已收金额',
          type: 'line',
          yAxisIndex: 1,
          data: receivedAmountData,
          smooth: true,
          symbolSize: 6,
          lineStyle: {
            color: '#67C23A',
            width: 2
          },
          itemStyle: {
            color: '#67C23A'
          }
        }
      ]
    };

    myChart.setOption(option);

    // 响应式处理
    const resizeChart = () => {
      if (myChart && !myChart.isDisposed()) {
        myChart.resize();
      }
    };
    chartResizeHandler.value = resizeChart;
    window.addEventListener('resize', resizeChart);
  } catch (error) {
    console.error('渲染图表失败:', error);
    const chartDom = document.getElementById('completionRateChart');
    if (chartDom) {
      chartDom.innerHTML =
        '<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #f56c6c;">图表渲染失败</div>';
    }
  }
};

/**
 * 表格行样式
 */
const tableRowClassName = ({ row }: { row: any }) => (row.isEditing ? 'editing-row' : '');

onMounted(() => {
  getProjectDetail();
  getReceiveList();
});

onUnmounted(() => {
  // 清理resize事件监听器
  if (chartResizeHandler.value) {
    window.removeEventListener('resize', chartResizeHandler.value);
    chartResizeHandler.value = null;
  }

  // 清理图表实例
  if (chartInstance.value) {
    chartInstance.value.dispose();
    chartInstance.value = null;
  }
});
</script>

<style lang="scss" scoped>
.app-container {
  padding: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding-bottom: 10px;
  border-bottom: 1px solid #ebeef5;
  background: #fff;
  min-height: 48px;

  .card-header-left {
    display: flex;
    align-items: center;
    gap: 12px;

    .title {
      font-size: 16px;
      font-weight: 600;
      color: #303133;
    }

    .el-button {
      transition: all 0.2s ease;
    }

    .el-button:hover {
      transform: translateY(-1px);
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    }
  }

  .right {
    display: flex;
    align-items: center;
  }
}

.receive-container {
  :deep(.el-table) {
    .el-table__cell {
      vertical-align: middle;
    }
  }
}

.scroll-tip {
  display: inline-block;
  font-size: 12px;
  color: #909399;
  background-color: #f5f7fa;
  border: 1px solid #e4e7ed;
  padding: 6px 12px;
  border-radius: 4px;
}

.text-overflow {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  vertical-align: top;
}

.text-gray-400 {
  color: #a0aec0;
}

/* 回款卡片样式 */
.receive-card {
  margin-bottom: 40px;
  padding-bottom: 30px;
  border-radius: 12px;
}

/* 统计卡片样式 */
.statistics-card {
  background: linear-gradient(135deg, #f8faff 0%, #f0f7ff 100%);
  border: 1px solid #e1ecff;
  box-shadow: 0 2px 12px rgba(64, 158, 255, 0.08);
  border-radius: 12px;
}

.statistics-header {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--el-color-primary);
  font-weight: 600;
}

.statistics-icon {
  font-size: 20px;
  color: var(--el-color-primary);
}

.statistics-title {
  font-size: 16px;
  color: var(--el-text-color-primary);
}

.statistics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 24px;
  padding: 20px 0;
}

.stat-item {
  text-align: center;
  padding: 20px 16px;
  background: #fff;
  border-radius: 12px;
  border: 1px solid #e1ecff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
  transition: all 0.3s ease;
}

.stat-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgba(64, 158, 255, 0.12);
}

.stat-label {
  font-size: 14px;
  color: var(--el-text-color-regular);
  margin-bottom: 8px;
  font-weight: 500;
}

.stat-value {
  font-size: 24px;
  font-weight: bold;
  margin-bottom: 8px;
  line-height: 1.2;
}

.stat-value.total-amount {
  color: #1f2937;
}

.stat-value.received-amount {
  color: #10b981;
}

.stat-value.surplus-amount {
  color: #f59e0b;
}

.stat-value.completion-rate {
  color: var(--el-color-primary);
}

.stat-desc {
  font-size: 12px;
  color: var(--el-text-color-placeholder);
  line-height: 1.4;
}

/* 编辑状态行背景色 */
:deep(.editing-row) {
  background-color: var(--el-color-primary-light-9);
}

:deep(.editing-row td) {
  background-color: var(--el-color-primary-light-9) !important;
}

/* 表格内的小尺寸组件调整 */
.receive-container :deep(.el-input__wrapper) {
  min-height: 28px;
}

.receive-container :deep(.el-select .el-input__wrapper) {
  min-height: 28px;
}

.receive-container :deep(.el-textarea__inner) {
  min-height: 60px;
  resize: vertical;
}

/* 小尺寸标签样式 */
.receive-container :deep(.el-tag--small) {
  height: 20px;
  line-height: 18px;
  font-size: 11px;
  padding: 0 4px;
}

/* 操作按钮组样式 */
.receive-container :deep(.el-button + .el-button) {
  margin-left: 4px;
}

/* 表单验证错误样式 */
.receive-container :deep(.is-error .el-input__wrapper) {
  border-color: #f56c6c !important;
  box-shadow: 0 0 0 1px #f56c6c inset !important;
}

.receive-container :deep(.is-error .el-input__wrapper:hover) {
  border-color: #f56c6c !important;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .app-container {
    padding: 8px;
  }

  .card-header {
    flex-direction: column;
    gap: 16px;
    align-items: stretch;
  }

  .card-header .left {
    flex-wrap: wrap;
    gap: 8px;
  }

  /* 统计卡片响应式 */
  .statistics-grid {
    grid-template-columns: 1fr;
    gap: 16px;
    padding: 16px 0;
  }

  .stat-item {
    padding: 16px 12px;
  }

  .stat-value {
    font-size: 20px;
  }

  .stat-label {
    font-size: 13px;
  }

  .stat-desc {
    font-size: 11px;
  }
}

/* 日志弹窗样式 */
.log-dialog :deep(.el-dialog__body) {
  padding: 20px;
}

.log-container {
  min-height: 400px;
}

.chart-card {
  margin-bottom: 20px;
  background: linear-gradient(135deg, #f8faff 0%, #f0f7ff 100%);
  border: 1px solid #e1ecff;
  box-shadow: 0 2px 12px rgba(64, 158, 255, 0.08);
}

.chart-header {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--el-color-primary);
  font-weight: 600;
}

.chart-icon {
  font-size: 18px;
}

#completionRateChart {
  background: #fff;
  border-radius: 8px;
  border: 1px solid #e1ecff;
}

.log-header {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--el-text-color-primary);
  font-weight: 600;
}

.log-icon {
  font-size: 18px;
}

.dialog-footer {
  text-align: center;
  padding: 20px 0;
}

/* 响应式调整 */
@media (max-width: 1200px) {
  .inline-user-selector {
    min-width: 120px;
  }

  .selected-users-inline {
    max-height: 60px;
    overflow-y: auto;
  }
}

/* 内联用户选择器样式 */
.inline-user-selector {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 100%;
}

.selected-users-inline {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  min-height: 20px;
}

.inline-select-btn {
  align-self: flex-start;
  padding: 4px 8px;
  font-size: 12px;
  height: auto;
  min-height: 24px;
}
</style>
